package notentool;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.Console;
import java.io.File;
import java.io.IOException;
import java.util.InputMismatchException;
import java.util.Scanner;
import java.util.concurrent.TimeUnit;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.table.DefaultTableModel;

import notentool.QISDataHandler.SemNote;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

/*
 * Wichtig: 
 *  - Fehlerausgaben bitte mit Errors.addError(String "FEHLERTEXT", int Fehlernr); hinzufügen
 *     + neuen Fehler in ErrorCodes.txt hinzufügen
 *  - für Erfolgsmeldungen bitte den Debug Modus nutzen:
 *     if( DEBUG ) System.out.println("MEINE MELDUNG");
 */

public class NotenManager {
	static private int matrikel=0;
	static private String pw=null;
	static private QISDataHandler data=null;
	static StudentView sv1;
	static String defaultXML = "default.xml";
	static DefaultTableModel tableModel;
	static String latestSaveFile = defaultXML;
	
	
	/* returns false if the xml file not exist or something is wrong */
	static boolean getLogin(String filename){
		
		if( null == filename || "".contentEquals(filename) ){
			Errors.addError("Falschen Parameter übergeben. >null< oder \"\" ist nicht möglich.", 8);
			return false;
		}
		SAXBuilder builder = new SAXBuilder();
		
		Document doc;
		try {
			doc = builder.build(new File(filename));
			Element student = doc.getRootElement();
			if( null == student ){
				System.out.println("DEBUG1");
			}
		//	if( null == pw ) // do not overwrite if the pw was already set
				pw = student.getAttributeValue("pw").toString();
			
			try{
				//	if( 0 == matrikel ) // do not overwrite if the matrikel was already set
				matrikel = Integer.parseInt(student.getAttributeValue("matrikel").toString()); 
			}catch( NumberFormatException e){
				Errors.addError("Matrikelnr >" + student.getAttributeValue("matrikel").toString() +"< ist keine gültige Nummer", 17);
				matrikel=0;
			}
			
			if ( null == pw || matrikel == 0 ){ // something was wrong
				return false;
			}

		} catch (JDOMException e1) {
			Errors.addError("Fehler beim Laden der XML-Datei: " + filename, 7);
			return false;
		} catch (IOException e1) {
			if( !filename.contentEquals(defaultXML) )
				Errors.addError("Fehler, Datei kann nicht gefunden bzw. geöffnet werden!: " + filename, 9);
			return false;
		}
			
	return true;	
	}
		
	/* sorts the java arguments, and starts the commands */
	@SuppressWarnings("unused")
	static public void runArguments( String[] args ){
		// variables for arguments which have to run in a special order
		int matrikel_tmp=0;
		String pw_tmp=null, xmlFilename=null;
		Boolean menu=false, debug=false, clear=false;
		
		
		// try to get login from default file
		Errors.stopAddErrors();
		getLogin(defaultXML);
		Errors.startAddErrors();
		
		//loop 1, fill the important variables 
		int newArgsLen=0; // the new length for the args Array, will set in the first loop
		for( int i=0; i<args.length; i++){ 
			String tmp = (null == args[i])?"":args[i].toLowerCase(); // for the usability 
			if( "--matrikel".contentEquals(tmp) || "-ma".contentEquals(tmp) || "--user".contentEquals(tmp) || "-u".contentEquals(tmp)){
				++i;
				if( i >= args.length )
					Errors.addError("Nach der Option " + args[i-1] + " wurde kein weiterer Parameter angegeben!", 10);
				else{
					try{ matrikel=Integer.parseInt(args[i]); }
					catch( NumberFormatException e ){
						matrikel_tmp=0;
						Errors.addError("Ungültige Zahl >" + args[i] + "< als Matrikelnummer eingegeben!", 11);
					}
				}
			}
			else if ( "--pass".contentEquals(tmp) || "-p".contentEquals(tmp) ){
				++i;
				if( i >= args.length )
					Errors.addError("Nach der Option " + args[i-1] + " wurde kein weiterer Parameter angegeben!", 10);
				else 
					pw_tmp = args[i];
			}
			else if( "--login-file".contentEquals(tmp) || "-lf".contentEquals(tmp) ){
				++i;
				if( i >= args.length )
					Errors.addError("Nach der Option " + args[i-1] + " wurde kein weiterer Parameter angegeben!", 10);
				else 
					getLogin( args[i] );		
			}
			else if( "--debug".contentEquals(tmp) || "-d".contentEquals(tmp))
				debug=(debug)?false:true;
			else if( "--menu".contentEquals(tmp) || "-m".contentEquals(tmp))
				menu=true;
			else{ // the arguments which will are used later
				args[newArgsLen]=args[i];
				newArgsLen++;
			}
		}
		
		// load login from xmlFilname (parameter was given), overwrites default login
		if( null != xmlFilename )
			getLogin(xmlFilename); //sets the static matrikel and pw
		
		// run the important arguments in a useful order
		if( 0 != matrikel_tmp )
			matrikel=matrikel_tmp; // matrikel via parameter has the highest priority. overwrite matrikel from xmlFile if it was set
		if( null != pw_tmp )
			pw=pw_tmp; // pw via parameter has the highest priority. overwrite matrikel from xmlFile if it was set
		
		// now we must have the correct login, so we can load the other information from xmlFile
//		if( null != xmlFilename )
//			getLogin(xmlFilename);
		
		// create the local data structure
		data = new QISDataHandler(matrikel, pw);
		data.ignoreCertificates();
		data.DEBUG=debug;
		// try to load default data
		if( null == xmlFilename){
			Errors.stopAddErrors(); 
			data.loadFromXML(defaultXML);
			Errors.startAddErrors();
		}
		
		// loop 2, for this arguments are no order required
		for( int i=0; i<newArgsLen; i++){
			String tmp = (null == args[i])?"":args[i].toLowerCase(); // for the usability 
			if ( "--gui".contentEquals(tmp) || "-g".contentEquals(tmp) )
				System.out.println("Run GUI");
			else if( "--wavg".contentEquals(tmp) || "-w".contentEquals(tmp) )
				System.out.println("Gewichteter durchschnitt: " + data.calcWeightedAverage());
			else if( "--avg".contentEquals(tmp) || "-a".contentEquals(tmp) )
				System.out.println("Durchschnitt: " + data.calcAverage() );
			else if( "--help".contentEquals(tmp) || "-h".contentEquals(tmp) )
				printHelp();
			else if( "--show-options".contentEquals(tmp) || "-so".contentEquals(tmp) )
				printOptions();
			else if( "--download".contentEquals(tmp) || "-dl".contentEquals(tmp) )
				data.loadDataFromQIS();
			else if( "--show-current".contentEquals(tmp) || "-sc".contentEquals(tmp) ){
				data.loadDataFromQIS();
				data.printModuls();
			}
			else if( "--statistics".contentEquals(tmp) || "-st".contentEquals(tmp) )
				System.out.println(createStatistics());
			else if( "--show".contentEquals(tmp) || "-sh".contentEquals(tmp) )
				data.printModuls();
			else if( "--show-saved".contentEquals(tmp) || "-ss".contentEquals(tmp) ){
				++i;
				if( i >= args.length )
					Errors.addError("Nach der Option " + args[i-1] + " wurde kein weiterer Parameter angegeben!", 10);
				else 
					data.loadFromXML(args[i]);
					data.printModuls();
			}
			else if( "--save-to-file".contentEquals(tmp) || "-stf".contentEquals(tmp) ){
				++i;
				if( i >= args.length )
					Errors.addError("Nach der Option " + args[i] + " wurde kein weiterer Parameter angegeben!", 10);
				else
					data.saveCurrentDataToXml(args[i]);
			}
			else if( "--save".contentEquals(tmp) || "-s".contentEquals(tmp) )
				data.saveCurrentDataToXml(defaultXML);
			else if( "--load-from-file".contentEquals(tmp) || "-lff".contentEquals(tmp) ){ 
				++i;
				if( i >= args.length )
					Errors.addError("Nach der Option " + args[i] + " wurde kein weiterer Parameter angegeben!", 10);
				else
					data.loadFromXML(xmlFilename);
			}
			else if ("--check".contentEquals(tmp) || "-c".contentEquals(tmp)){
				if ( data.checkListForNewModules() ){
					System.out.println("Es wurde mindestens eine neue Note heruntergeladen!");
				}else{
					System.out.println("Keine neuen Noten!");
				}
			}
			else if( "--check-show".contentEquals(tmp) || "-cs".contentEquals(tmp)){
				if( !data.printNewModules() )
					System.out.println("Keine neuen Noten!");
			}
			else if( "--load".contentEquals(tmp) || "-l".contentEquals(tmp) )
				data.loadFromXML(defaultXML);
			else if( "--delete-tmp-data".contentEquals(tmp) || "-dtd".contentEquals(tmp) || "--clear".contentEquals(tmp) || "-cl".contentEquals(tmp))
				clear=true;
			else
				Errors.addError("unbekannte Option: " + args[i] + ". -so zeigt alle Optionen an.", 12);
		}
		
		// menu have to be start on the end
		if( menu )
			runMenu();
		
		//the user doesn't want to store program data
		if( clear ){
			System.out.println("Funktion muss noch geschrieben werden!");
		}
		
	}
	
	/* prints a long help text*/
	static void printHelp(){
		System.out.println("Benutzung: java -jar Notenmanger [Option...]");
		System.out.println(" Ohne Optionen wird die Automatisch die GUI gestartet.");
		System.out.println(" Optionen:");
		System.out.println("\tDurchschnitt berechnen und ausgeben:\n\t  --avg, -a" );
		System.out.println("\tAktuellen Datenpuffer auf neue Noten prüfen:\n\t --check, -c");
		System.out.println("\tAktuellen Datenpuffer auf neue Noten prüfen und sie ggf. anzeigen:\n\t --check-show, -cs");
		System.out.println("\tDebugmodus ein-/ ausschalten:\n\t  --debug, -d");
		System.out.println("\tDie vom Programm erzeugen Daten löschen.:\n\t --delete-tmp-data, -dtd, -clear, -cl");
		System.out.println("\tNoten vom QIS-Portal in das Programm laden:\n\t  --download, -dl");
		System.out.println("\tLogindaten aus XML-Datei laden:\n\t  --login-file, -lf DATEINAME");
		System.out.println("\tDie grafische Oberfläche starten:\n\t  --gui, -g");
		System.out.println("\tDiese Hilfe aufrufen:\n\t  --help, -h");
		System.out.println("\tNoten aus der XML-Datei laden:\n\t  --load-from-file, -lff DATEINAME");
		System.out.println("\tNoten aus der Standarddatei (default.xml) laden:\n\t  --load, -l");
		System.out.println("\tDie Matrikelnummer angeben:\n\t  --matrikel, -ma, --user, -u MATRIKELNUMER");
		System.out.println("\tInteraktives Menü starten:\n\t  --menu, -m");
		System.out.println("\tDas Passwort angeben:\n\t  --pass, -p PASSWORT");
		System.out.println("\tAktuellen Stand in Standdarddatei (default.xml) speicher:\n\t  --save, -s");
		System.out.println("\tAktuellen Stand in Datei speichern:\n\t  --save-to-file, -stf DATEINAME");
		System.out.println("\tNoten herunterladen und anzeigen:\n\t  --show-current, -sc");
		System.out.println("\tOptionen anzeigen:\n\t  --show-options, -so");
		System.out.println("\tGespeicherte Daten aus Datei laden und anzeigen:\n\t  --show-saved, -ss");
		System.out.println("\tAktuellen Datenpuffer anzeigen:\n\t  --show, -sh");
		System.out.println("\tStatistiken anzeigen:\n\t  --statistics, -st");
		System.out.println("\tNach Credits gewichten Durchschnitt anzeigen:\n\t  --wavg, -w");
		System.out.println("Bei den nachfolgenden Parametern ist die Reihenfolge relevant.\n" +
				" Sie beziehen sich immer auf die aktuell geladenen Daten.\n" +
				" Zum Beispiel führt --load --download --save dazu das die alten Daten" +
				" geladen werden, anschließend aktualisiert und danach gespeichert werden.\n" +
				" --download --load --save würde dagegen die neuen Daten verwerfen und die alten speichern.");
		System.out.println(" Zeitpunktabhängige Optionen:");
		System.out.println("\t--avg, -a");
		System.out.println("\t--check, -c");
		System.out.println("\t--check-show, -cs");
		System.out.println("\t--debug, -d");	
		System.out.println("\t--save, -s");
		System.out.println("\t--save-to-file, -stf DATEINAME");
		System.out.println("\t--show-current, -sc");
		System.out.println("\t--show, -sh");
		System.out.println("\t--statistics, -st");
		System.out.println("\t--wavg, -w");
		
		System.out.println("Beispielbenutzung:\n java -jar Notenmanager -u 12345 -p 'Passwort' --download --save --show --statistics");
	}
	
	/* prints a short information about the options */
	static void printOptions(){
		System.out.println("Benutzung: java -jar Notenmanger [Option...]");
		System.out.println("Nähre Informationen erhalten Sie durch --help");
		System.out.println(" Ohne Optionen wird die Automatisch die GUI gestartet.");
		System.out.println(" Optionen:");
		System.out.println("\t--avg, -a");
		System.out.println("\t--check, -c");
		System.out.println("\t--check-show, -cs");
		System.out.println("\t--debug, -d");
		System.out.println("\t--delete-tmp-data, -dtd, -clear, -cl");
		System.out.println("\t--download, -dl");
		System.out.println("\t--login-file, -lf DATEINAME");
		System.out.println("\t--gui, -g");
		System.out.println("\t--help, -h");
		System.out.println("\t--load-from-file, -lff DATEINAME");
		System.out.println("\t--load, -l");
		System.out.println("\t--matrikel, -ma, --user, -u MATRIKELNUMMER");
		System.out.println("\t--menu, -m");
		System.out.println("\t--pass, -p PASSWORT");
		System.out.println("\t--save, -s");
		System.out.println("\t--save-to-file, -stf DATEINAME");
		System.out.println("\t--show-current, -sc");
		System.out.println("\t--show-options, -so");
		System.out.println("\t--show-saved, -ss");
		System.out.println("\t--show, -sh");
		System.out.println("\t--statistics, -st");
		System.out.println("\t--wavg, -w");
	}
	
	/* starts an interactive menu*/
	static void runMenu(){
		Errors.printErrorList();
		//Errors.deepCopy();
		System.out.println("Falls Sie das Programm das erste mal verwenden,\n" +
				"versuchen Sie die Optionen 10, 11 und danach 5.");
	
		@SuppressWarnings("resource")
		Scanner sc = new Scanner(System.in);
		String tmp=null; // to query empty lines
		int option=1;
		while( option!=0 ){
			switch( option ){
			case 1:
				System.out.println("~~~~~~~~~~~~Menü~~~~~~~~~~~~");
				System.out.println("0  - Menü verlassen");
				System.out.println("1  - Menü anzeigen");
				System.out.println("2  - Durchschnitt anzeigen");
				System.out.println("3  - Gewichteten Durchschnitt anzeigen");
				System.out.println("4  - Temporäre Daten löschen");
				System.out.println("5  - Noten herunterladen und in intere Datenstruktur bringen");
				System.out.println("6  - Benutzername und Passwort aus XML-Datei laden");
				System.out.println("7  - Grafische Oberfläche starten");
				System.out.println("8  - Hilfeinformationen für Parameter anzeigen");
				System.out.println("9  - Noten aus XML-Datei laden");
				System.out.println("10 - Matrikelnummer setzen");
				System.out.println("11 - Passwort setzen");
				System.out.println("12 - Aktuelle Datenstruktur in XML-Datei speichern");
				System.out.println("13 - Geladene Noten anzeigen");
				System.out.println("14 - Parameter Optionen anzeigen");
				System.out.println("15 - Gespeicherte Daten laden und anzeigen (9+13)");
				System.out.println("16 - Statistiken anzeigen");
				System.out.println("17 - Durchschnitt anzeigen");
				System.out.println("18 - Debugmodus an/aus.");
				System.out.println("19 - Überprüfe ob neue Noten geladen wurden.");
				System.out.println("20 - Überprüfe ob neue Noten geladen wurden und zeige sie ggf. an");
				System.out.println("21 - Überprüfe ob neue Noten im QIS sind");
				System.out.println("22 - Überprüfe ob neue Noten im QIS sind und zeige sie ggf. an");
				System.out.println("~~~~~~~~~~Menüende~~~~~~~~~~");
				break;
			case 2:
				System.out.println("Durchschnitt: " + data.calcAverage());
				break;
			case 3:
				System.out.println("Gewichteter Durchschnitt: " + data.calcWeightedAverage());
				break;
			case 4:
				System.out.println("In Arbeit"); //TODO
				break;
			case 5:
				data.loadDataFromQIS();
				break;
			case 6:
				System.out.println("LEER = default.xml");
				System.out.print("Dateiname: ");
				tmp=new Scanner(System.in).nextLine();
				if( 0 >= tmp.length() )
					tmp=defaultXML;
				if( !getLogin(tmp) )
					Errors.printLastError();
				break;
			case 7:
				System.out.println("Starte GUI - noch in arbeit!");
				break;
			case 8:
				printHelp();
				break;
			case 9:
				Errors.clearArrayList();
				System.out.println("LEER = default.xml");
				System.out.print("Dateiname: ");
				tmp=new Scanner(System.in).nextLine();
				if( 0 >= tmp.length() )
					tmp=defaultXML;
				data.loadFromXML(tmp);
				Errors.printErrorList();
				break;
			case 10:
				Errors.clearArrayList();
				System.out.print("Matrikelnummer: ");
				data.setMatrikel(sc.next());
				Errors.printErrorList();
				break;
			case 11:
			    Console console = System.console();
			    if (console == null) {
			        System.out.println("Kann keine Consoleninstanz bekommen. ACHTUNG! Passwort wird angezeigt!");
			        System.out.print("Passwort: ");
			        data.setPw(new Scanner(System.in).nextLine());
			    }else{
			    	data.setPw( String.valueOf(console.readPassword("Passwort: ")) );
			    }
				break;
			case 12:
				System.out.println("Achtung, evtl. vorhandene Datei wird überschrieben!");
				System.out.println("LEER = default.xml");
				System.out.print("Dateiname: ");
				tmp=new Scanner(System.in).nextLine().toString();

				if( 0 >= tmp.length() )
					tmp=defaultXML;
				
				data.saveCurrentDataToXml(tmp);
				int errorId = Errors.printErrorByErrorCode(18);
				if( 0 <= errorId )
					Errors.removeErrorById(18);
				break;
			case 13:
				data.printModuls();
				break;
			case 14:
				printOptions();
				break;
			case 15:
				Errors.clearArrayList();
				System.out.println("LEER = default.xml");
				System.out.print("Dateiname: ");
				tmp=new Scanner(System.in).nextLine();
				if( tmp.isEmpty() )
					tmp=defaultXML;
				data.loadFromXML(tmp);
				if( Errors.isEmpty() )
					data.printModuls();
				else
					Errors.printErrorList();
				break;
			case 16:
				System.out.println(createStatistics());
				break;
			case 17:
				System.out.println("Durchschnitt: " + data.calcAverage());
				break;
			case 18:				
				if( data.DEBUG ){
					data.DEBUG = false;
					System.out.println("Debug Modus ist jetzt aus! ");
				}else{
					data.DEBUG = true;
					System.out.println("Debug Modus ist jetzt an!");
				}
				break;
			case 19:
				if ( data.checkListForNewModules() ){
					System.out.println("Es wurde mindestens eine neue Note heruntergeladen!");
				}else{
					System.out.println("Keine neuen Noten!");
				}
				break;
			case 20:
				if( !data.printNewModules() )
					System.out.println("Keine neuen Noten!");
				break;
			case 21:
				data.loadDataFromQIS();
				option = 19;
				continue;
			case 22:
				data.loadDataFromQIS();
				option = 20;
				continue;
			default:
				System.out.println("Option >" + option + "< existiert nicht. 1 zeigt das Menü an");
			}
	
			System.out.print("Option: ");
			try{
				option = sc.nextInt();
			}catch( InputMismatchException e ){
				option = 1; 
				sc.nextLine();
			}
			
		}
		
	}
	
	/* Loads the date an updates the progress bar */
	public static boolean loadDataUseProgressBar( DefaultTableModel tableModel ){
		sv1.progressBar.setMaximum(100);
		
		Thread t = new Thread("loadDataUseProgressBar"){
			public void run() {
				// i = timeout in seconds
				for(int i=0; i<(100*4); i++){
					sv1.progressBar.setValue(data.progress);
            	  //System.out.println(data.progress
					try {
						TimeUnit.MILLISECONDS.sleep( 250 );
					} catch (InterruptedException e) {
						return;
					}
				}
			}};
		t.start();
		
		if( ! data.loadDataFromQIS() ){
			t.interrupt();
			Errors.printLastError();
			JOptionPane.showMessageDialog(sv1, Errors.getLastErrorMsg(), "Fehlernummer: " + Errors.getLastErrorCode(), JOptionPane.ERROR_MESSAGE );
			sv1.progressBar.setValue(0);
			return false;
		}
		
		loadDataInGUI(tableModel);
		t.interrupt();
		sv1.progressBar.setValue(0);
		return true;
		
	}
	
	/* Loads the current program data in the GUI */
	public static boolean loadDataInGUI(DefaultTableModel tableModel){
		
		// remove rows if table is large enough; i know that's stupid, but the update method doesn't work for me
		for( int i=tableModel.getRowCount()-1; i >= 0; i--)
			tableModel.removeRow(i);
		
		// add new rows
		for( int i=0; i < data.getModuleListSize(); i++ ){
			Object[] tmp_raw = data.getModuleRaw(i);
			if( null != tmp_raw)
				tableModel.addRow( tmp_raw );			
		}
		
		// TODO Test
		sv1.textPanelStatistics.setText(createStatistics());
		sv1.setSemNoten(data.getSemNoten());
		sv1.repaint();
		return true;
	}
	
	/* Starts the GUI*/
	public static boolean runGUI(){
		
		sv1 = new StudentView(); // Contains the mark table
		sv1.placeScreenMid(sv1);
		tableModel = (DefaultTableModel) sv1.tableModules.getModel(); // Control the mark table
		
		// init all Buttons //
		
		sv1.btnSetLogin.addActionListener(new HandleBtnLoginSetzen());
		
		// all for the PopupSaveFile 
		sv1.btnDatenSpeichern.addActionListener(new HandlebtnDatenSpeichern()); 
		
		sv1.btnLoadAndUpdateData.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				new Thread(){
					public void run(){
						sv1.btnLoadAndUpdateData.setEnabled(false);
						loadDataUseProgressBar(tableModel);
						sv1.btnLoadAndUpdateData.setEnabled(true);
						
						if( data.checkListForNewModules() ){
							System.out.println("neue noten!!!!!");
							JOptionPane.showMessageDialog(sv1, "Neue Noten wurden heruntergeladen! :)" + data.getNewModules());
							System.out.println();
						}
						
						sv1.textPanelStatistics.setText(createStatistics());
					};
				}.start();
			}
		});
		sv1.btnDatenLadenlokal.addActionListener(new HandlebtnDatenLaden());
		
		loadDataInGUI(tableModel);
		sv1.textPanelStatistics.setText(createStatistics());
		return true;
	}
	
	public static String createStatistics(){
		String stat =
			"Matrikel:\n\t "+ data.getMatrikel() + "\n"
			+ "Durchschnitt:\n\t"+ data.getAvg() + "\n"
			+ "Gewichteter Durchschnitt:\n\t"+ data.getWavg() + "\n"
			+ "Durchschnitt nach Prüfungsordnung:\n\t" + Math.floor(data.getWavg()*10)/10 + "\n"
			+ "Summe Credits:\n\t" + data.getSumCredits() + "\n"
			+ "\nNach Semestern:\n"
		;
		for(SemNote s : data.getSemNoten()){
			stat+=s.getSemester() + "\n   Summe Credits:   " + s.getCredits() + "\n   Gewichteter Durchschnitt:   " + s.getAvg() + "\n\n";
		}
		/*
		String [][] statList = data.calcStatisticsBySemester();
		if(statList == null)
			return "Konnte keine Statistiken laden!";
		for(int i=0; i<statList.length; i++){
			if( statList[i].length > 2 ){
				stat += (statList[i][0] + "\n   Summe Credits:   " + statList[i][1] + 
						"\n   Gewichteter Durchschnitt:   " + statList[i][2] +
						"\n\n"
						);
			}
		}*/
		
		return stat;
	}
	
	/* fills the progressBar within <milliseconds> and refreshes it <updates> times.
	 * setMax = how high the progressBar should climb
	 * */
	public static Thread runProgressbar( final long milliseconds, final int updates, final double setMax ){
	//	sv1.progressBar.setMaximum(updates);
		
		final Thread t = new Thread("barThread"){
			public void run() {
				if( 0 == updates ){
					try {
						Thread.sleep(milliseconds, 0);
						sv1.progressBar.setValue( 
							(0==setMax) ? sv1.progressBar.getMaximum() : (int)setMax
						);
					} catch (InterruptedException e){
					}
					return;
				}
				
				for ( long i = 0; i <= updates; ++i ){
					
					final int j = (int) (((sv1.progressBar.getMaximum()*setMax/100)/updates)*i);
					try {
						sleep(milliseconds/updates, 0);
						sv1.progressBar.setValue( j );
					}catch (InterruptedException e) {
						break;
					}
				}
				sv1.progressBar.setValue( 
						(0==setMax) ? sv1.progressBar.getMaximum() : (int)setMax
					);
			}
		};
			
		t.start();
		return t;
		
	}
	
	// Handler to open the loginpopup
 	static class HandleBtnLoginSetzen implements ActionListener{
		public void actionPerformed(ActionEvent evt){
			////System.out.println("Login setzen gedrückt");
			sv1.openPopLogin(String.valueOf(matrikel), pw );
			
			/* abbrechen button in loginpopup was pressed */
			sv1.popLogin.btnAbbrechen.addActionListener( new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					sv1.popLogin.setVisible(false);
					sv1.popLogin.setPassword(pw);
					sv1.popLogin.setMatrikel(String.valueOf(matrikel));
				}
			});
			
			// OK button in login popup was pressed
			sv1.popLogin.btnSpeichern.addActionListener( new ActionListener() {
				public void actionPerformed(ActionEvent evt0){
					pw = sv1.popLogin.getPassword();
					data.setPw( pw );

					int matrikel_tmp=sv1.popLogin.getMatrikel();

					if( -1 != matrikel_tmp )
						sv1.popLogin.setVisible(false);
						matrikel = matrikel_tmp;
						data.setMatrikel(matrikel_tmp);
					}
			});
			
		}		
	}
  	
	/* handler for the "speichern" Popup */
	static class HandlebtnDatenSpeichern implements ActionListener{
		//ActionListener alAbbrechen = null;
		public void actionPerformed(ActionEvent evt){
			//System.out.println("Login setzen gedrückt");
			/* initialize and open the popup */
			sv1.openPopSave();
			sv1.popSave.setFileLocation(latestSaveFile);
			// add actionListner if the button don't have one.
			if (sv1.popSave.btnAbbrechen.getListeners(java.awt.event.ActionListener.class).length == 0) {
				sv1.popSave.btnAbbrechen.addActionListener( new ActionListener() {
					public void actionPerformed(ActionEvent evt){
						latestSaveFile = sv1.popSave.getFileLocation();
						sv1.popSave.setVisible(false);
						sv1.popSave.restoreOKSubmit();
					}
				});  
			}
			// add actionListner if the button don't have one.
			if (sv1.popSave.btnSpeichern.getListeners(java.awt.event.ActionListener.class).length == 0) {
				sv1.popSave.btnSpeichern.addActionListener( new ActionListener() {
					public void actionPerformed(ActionEvent evt0){
						sv1.popSave.storeOKSubmit();
						data.saveCurrentDataToXml(sv1.popSave.getFileLocation(), !sv1.popSave.chckbxSaveNoLogin.isSelected());
						latestSaveFile = sv1.popSave.getFileLocation();
						sv1.popSave.setVisible(false);
					}
				});
			}
		}
	}
	
	static class HandlebtnDatenLaden implements ActionListener{
		public void actionPerformed(ActionEvent evt){
			JFileChooser fc = new JFileChooser();
			fc.setSelectedFile(new File(latestSaveFile));
			int state = fc.showOpenDialog( null );
			if ( state == JFileChooser.APPROVE_OPTION ){
				String filename = fc.getSelectedFile().getAbsolutePath();
				data.loadFromXML(filename);
				
				int mat_tmp = matrikel;
				String pw_tmp = pw;
				if( getLogin(filename) ){
					data.setMatrikel(matrikel);
					data.setPw(pw);
				}else{
					matrikel = mat_tmp;
					pw = pw_tmp;
				}
				mat_tmp=0;
				pw_tmp = null;
				
				loadDataInGUI(tableModel);
				if(data.DEBUG) 
					System.out.println("Datei geladen: " +  fc.getSelectedFile().getAbsolutePath() );
				
				latestSaveFile = filename;
			}else
				if(data.DEBUG) 
					System.out.println( "Datei laden abgebrochen." );
		}
	}
	
	
	
	public static void main(String[] args) throws IOException {
		System.out.println("BETA: Bugs bitte an tim.malich@gmail.com senden.");
		Errors.stopAddErrors();
		getLogin(defaultXML);
		Errors.startAddErrors();
		if ( 0 == args.length ){
			System.out.println("Starte Oberfläche!");
			data = new QISDataHandler(matrikel, pw);
			data.ignoreCertificates();
			data.loadFromXML(defaultXML);
			runGUI();
		}else{
			runArguments(args);
		}

		if( !Errors.isEmpty() ){
			System.out.println("Während des Programmablaufs sind folgende Fehler aufgetreten: ");
			Errors.printErrorList();
		}
		System.out.println("Notentool beendet sich. :D");
	}

}
// Todo's and Notes
// TODO Spalten sortieren lassen
// TODO Startfenstergröße von Monitorgröße abhängig machen
// TODO login wird trotz haken beim mitgespeichert
// TODO leeres speichen = default.xml
// TODO Regex sufu
// TODO neue Noten hervorheben.